package com.ecoolex.discount.sales.core.service;

import java.nio.charset.StandardCharsets;
import java.security.KeyStore;
import java.security.PrivateKey;
import java.security.PublicKey;
import java.security.Signature;
import java.security.cert.CertificateFactory;
import java.security.cert.X509Certificate;
import java.security.interfaces.RSAPrivateCrtKey;
import java.util.Base64;
import java.util.Enumeration;


import lombok.extern.slf4j.Slf4j;
import org.springframework.core.io.Resource;

import com.ecoolex.discount.sales.core.properties.SignatureProperties;
import com.ecoolex.framework.common.enums.ResultCode;
import com.ecoolex.framework.common.exception.BizException;

@Slf4j
public class UnionPaySignatureService {

    private SignatureProperties signatureProperties;
    private PrivateKey privateKey;
    private PublicKey publicKey;

    public static final String X509 = "X.509";

    public static final String ALGORITHM = "SHA256WithRSA";

    public UnionPaySignatureService(SignatureProperties signatureProperties){
        this.signatureProperties = signatureProperties;
    }

    public void init() {
        privateKey = getSignaturePrivateKey();
        publicKey = getSignaturePublicKey();
    }

    private PrivateKey getSignaturePrivateKey() {
        try {
            Resource resource = signatureProperties.getPrivateKey();
            char[] charPassword = signatureProperties.getPassword().toCharArray();
            String alias = "";
            KeyStore keyStore = KeyStore.getInstance("PKCS12");
            keyStore.load(resource.getInputStream(), charPassword);
            Enumeration<String> e = keyStore.aliases();
            if (e.hasMoreElements()) {
                alias = e.nextElement();
            }
            return (RSAPrivateCrtKey) keyStore.getKey(alias, charPassword);
        }
        catch (Exception e) {
            log.error("获取签名私钥失败", e);
            throw new BizException(ResultCode.CALL.build(97), "获取签名私钥失败");
        }
    }

    private PublicKey getSignaturePublicKey() {
        try {
            Resource publicKeyResource = signatureProperties.getPublicKey();
            CertificateFactory certificatefactory = CertificateFactory.getInstance(X509);
            X509Certificate cert = (X509Certificate) certificatefactory.generateCertificate(publicKeyResource.getInputStream());
            return cert.getPublicKey();
        }
        catch (Exception e) {
            log.error("获取签名公钥失败", e);
            throw new BizException(ResultCode.CALL.build(97), "获取签名公钥失败");
        }
    }



    /**
     * 对数据进行签名
     * @param orgin 原文
     * @return 签名值
     */
    public byte[] signData(String orgin) {
        try {
            Signature sign = Signature.getInstance(ALGORITHM);
            sign.initSign(privateKey);
            byte[] byteData = orgin.getBytes(StandardCharsets.UTF_8);
            sign.update(byteData);
            return sign.sign();
        }
        catch (Exception e) {
            log.error("签名失败", e);
            throw new BizException(ResultCode.CALL.build(98), "签名失败");
        }
    }

    /**
     * 验证签名
     * @param plainText 原文
     * @param signature 签名
     * @return 是否验签通过
     */
    public boolean verify(String plainText, String signature) {
        try {
            Signature publicSignature  = Signature.getInstance(ALGORITHM);
            publicSignature.initVerify(publicKey);
            publicSignature.update(plainText.getBytes(StandardCharsets.UTF_8));
            byte[] signatureBytes = Base64.getDecoder().decode(signature.getBytes(StandardCharsets.UTF_8));
            return publicSignature.verify(signatureBytes);
        }catch (Exception e){
            log.error("验签失败", e);
            throw new BizException(ResultCode.CALL.build(98),"验签失败");
        }
    }
}
